<template>
    <div class="chatMessageRight">
        <el-popover
            trigger="click"
            :width="325"
            :show-arrow="false"
            placement="left"
            :teleported="false"
        >
            <template #reference>
                <div class="avatar"><img :src="userStore.avatar" /></div>
            </template>
            <FriendInfo :showType="0"></FriendInfo>
        </el-popover>
        <div v-if="message_type === 'text'" class="messageContainer">
            <div class="bubble">
                <span>{{ message }}</span>
            </div>
            <span class="arrow"></span>
        </div>
        <div
            :class="['audio', 'messageContainer']"
            v-else-if="message_type === 'audio'"
            @click="listenVoice"
        >
            <div :style="{ width: calculateBubbleWidth(duration!) + 'px' }" class="bubble">
                <span class="duration">{{ duration }}"</span>
                <SvgIcon name="audio-message" width="1.8rem" height="1.8rem" class="flip"></SvgIcon>
            </div>
            <span class="arrow"></span>
        </div>
        <div class="showImg" v-else-if="message_type === 'picture'">
            <el-image
                :src="mediaUrl"
                class="picture"
                :preview-src-list="[mediaUrl]"
                :zoom-rate="1.2"
                :max-scale="7"
                :min-scale="0.2"
                :style="{ width: file_width + 'px', height: file_height + 'px' }"
            >
                <template #placeholder>
                    <div class="imageSlot">
                        <SvgIcon name="img-load-error" width="20" height="20"></SvgIcon>
                    </div>
                </template>
                <template #error>
                    <div class="imageSlot">
                        <SvgIcon name="img-load-error" width="20" height="20"></SvgIcon>
                    </div>
                </template>
            </el-image>
        </div>
        <div class="videoPreview" v-else-if="message_type === 'video'" @click="openVideo">
            <el-image
                :src="showUrl"
                class="video-img"
                :style="{ width: file_width + 'px', height: file_height + 'px' }"
            >
                <template #placeholder>
                    <div class="imageSlot">
                        <SvgIcon name="img-load-error" width="20" height="20"></SvgIcon>
                    </div>
                </template>
                <template #error>
                    <div class="imageSlot">
                        <SvgIcon name="img-load-error" width="20" height="20"></SvgIcon>
                    </div>
                </template>
            </el-image>
            <span class="playBg">
                <span class="playIcon"></span>
            </span>
        </div>
        <div
            :class="['bubble', 'file-page']"
            v-else-if="message_type === 'file'"
            @click="openFile(mediaUrl, fileName)"
        >
            <div class="file-message">
                <span class="file-name">{{ fileName }}</span>
                <span class="file-size">{{ media_size }}</span>
            </div>
            <img class="file-img" :src="showUrl" alt="预览图加载失败" />
        </div>
    </div>
    <el-dialog
        v-model="ifShow"
        width="1000"
        align-center
        @close="dialogClose"
        :append-to-body="true"
    >
        <div class="show-area">
            <video
                :src="mediaUrl"
                alt="视频加载失败"
                class="play-video"
                v-if="message_type === 'video'"
                ref="playVideo"
                controls
                autoplay
            ></video>
        </div>
    </el-dialog>
</template>

<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { loadFile, calculateBubbleWidth, determineFileImage, downloadFile } from '@/utils/chatfile'
import { ElMessage } from 'element-plus'
import useUserStore from '@/store/modules/user'
import useMessagesStore from '@/store/modules/messages'

//获取父组件传递过来的全部数据
let props = defineProps({
    avatar: {
        type: String,
        required: true,
    },
    message: {
        type: String,
        required: true,
    },
    message_type: {
        type: String,
        required: true,
    },
    media_url: {
        type: String,
        required: false,
    },
    media_size: {
        type: String,
        required: false,
    },
    duration: {
        type: Number,
        required: false,
    },
    preview_url: {
        type: String,
        required: false,
    },
    file_width: {
        type: Number,
        required: false,
    },
    file_height: {
        type: Number,
        required: false,
    },
})

//预览图路径
let showUrl = ref<string>('')
//媒体源路径
let mediaUrl = ref<string>('')
//控制视频大屏播放dialog是否显示
let ifShow = ref<boolean>(false)
//video组件实例
let playVideo = ref<HTMLVideoElement>()
//文件名
let fileName: string
//使用用户仓库
const userStore = useUserStore()
//使用消息仓库
const messageStore = useMessagesStore()
//判断当前该条语音是否在播放
let isListening = ref<boolean>(false)

//打开视频的方法
const openVideo = () => {
    ifShow.value = true
    playVideo.value?.play()
}

//关闭弹窗时暂停视频的函数
const dialogClose = () => {
    playVideo.value!.pause() // 暂停视频
    playVideo.value!.currentTime = 0 // 将播放进度重置为0
}

//打开文件的方法
const openFile = (url: string, fileName: string) => {
    downloadFile(url, fileName)
}

//用户收听语音消息的方法
const listenVoice = async () => {
    if (messageStore.currentAudio && messageStore.audioUrl === props.media_url) {
        if (isListening.value) {
            messageStore.currentAudio.pause() //暂停当前音频
            isListening.value = !isListening.value
        } else {
            messageStore.currentAudio.play() //播放当前音频
            isListening.value = !isListening.value
        }
    }
    if (!messageStore.currentAudio || messageStore.audioUrl !== props.media_url) {
        if (messageStore.currentAudio) {
            messageStore.currentAudio.pause()
        }
        let Url = await loadFile(props.message_type!, props.media_url!)
        messageStore.audioUrl = props.media_url!
        //创建音频元素
        messageStore.currentAudio = new Audio(Url as string)
        //添加音频播放结束时的处理逻辑
        messageStore.currentAudio.addEventListener('ended', () => {
            isListening.value = false
            messageStore.currentAudio!.currentTime = 0 //重置播放进度
        })
        messageStore.currentAudio.play().catch((error) => {
            ElMessage.error('播放音频时出错：', error)
        })
        isListening.value = true
    }
}

onMounted(async () => {
    if (props.message_type !== 'text' && props.message_type !== 'audio') {
        try {
            showUrl.value = props.preview_url as string
            mediaUrl.value = (await loadFile(
                props.message_type,
                props.media_url as string,
            )) as string
            if (props.message_type === 'file') {
                fileName = props.media_url!.split('/').pop()!
                //获取文件扩展名
                const ext = fileName.split('.').pop()?.toLowerCase()
                //判定文件的具体类型，显示文件缩略图
                showUrl.value = determineFileImage(ext as string)
            }
        } catch (error) {
            ElMessage('消息加载失败')
        }
    }
})
</script>

<style scoped lang="scss">
.chatMessageRight {
    width: 100%;
    height: auto;
    margin: 0.75rem 0;
    padding: 0 1rem;
    @include flex-layout(flex, center, normal, nowrap, row-reverse);
}

.avatar {
    cursor: pointer;
    @include flex-layout(flex, center);

    img {
        width: calc($base-menu-height - 1rem);
        height: calc($base-menu-height - 1rem);
        border-radius: 0.5rem;
    }
}

/* 消息容器 */
.messageContainer {
    display: flex;
    align-items: center; /* 垂直居中 */
    max-width: 60%;
    margin-right: 1rem;
}

/* 消息气泡 */
.bubble {
    font-size: 1.5rem;
    line-height: 2rem;
    border-radius: 0.4rem;
    border: 1px solid rgb(214, 214, 214);
    background-color: white;
    padding: 0.5rem;
    word-wrap: break-word;
    @include flex-layout();
}

.bubble span {
    display: block;
    max-width: 100%;
}

/* 箭头 */
.arrow {
    width: 0;
    height: 0;
    border-style: solid;
    border-width: 5px 5px 5px 5px;
    border-color: rgb(214, 214, 214);
    transform: rotate(-45deg);
    position: relative;
    right: 5px;
}

.arrow::after {
    content: '';
    position: absolute;
    top: -6px;
    right: -4px;
    border-style: solid;
    border-width: 5px 5px 5px 5px;
    border-color: white;
}

.audio {
    height: 3rem;
    cursor: pointer;

    .audio-content {
        @include flex-layout(flex, center);
    }
}

.flip {
    transform: scaleX(-1);
}

.duration {
    font-size: 1.2rem;
    margin-left: auto;
}

.showImg {
    margin-right: 1.5rem;

    .picture {
        border: 1px solid rgba(33, 33, 33, 0.3);
        border-radius: 10px;
        cursor: pointer;
    }
}

.videoPreview {
    margin-right: 1.5rem;
    position: relative;
    cursor: pointer;
    border-radius: 10px; /* 统一圆角 */
}

.video-img {
    border: 1px solid rgba(33, 33, 33, 0.3);
    border-radius: 10px; /* 圆角 */
    transition:
        transform 0.3s ease,
        opacity 0.3s ease; /* 添加过渡效果 */
}

.videoPreview:hover .video-img {
    opacity: 0.95; /* 鼠标悬停时降低透明度 */
}

.playBg {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 50px; /* 固定大小 */
    height: 50px;
    background-color: rgba(35, 35, 35, 0.6); /* 半透明背景 */
    border-radius: 50%;
    transition:
        background-color 0.3s ease,
        transform 0.3s ease; /* 添加过渡效果 */
    @include flex-layout(flex, center, center);
}

.videoPreview:hover .playBg {
    background-color: rgba(35, 35, 35, 0.8); /* 鼠标悬停时加深背景 */
    transform: translate(-50%, -50%) scale(1.05); /* 鼠标悬停时放大 */
}

.playIcon {
    width: 0;
    height: 0;
    border-top: 10px solid transparent;
    border-bottom: 10px solid transparent;
    border-left: 15px solid #fff; /* 播放箭头 */
    transition: transform 0.3s ease; /* 添加过渡效果 */
}

.videoPreview:hover .playIcon {
    transform: scale(1.1); /* 鼠标悬停时放大箭头 */
}

.file-page {
    width: 20rem;
    height: 8rem;
    margin-right: 1.5rem;
    background-color: white;
    @include flex-layout(flex, center);
    cursor: pointer;

    &:hover {
        background-color: rgb(220, 220, 220);
        transition: all 0.5s;

        &::after {
            border-color: transparent transparent transparent rgb(220, 220, 220);
            transition: all 0.5s;
        }
    }

    &::after {
        border-color: transparent transparent transparent white;
    }

    .file-message {
        flex: 0.7;
        height: 100%;

        .file-name {
            @include ellipsis-multiple(-webkit-box, 2);
            height: calc(100% - 3rem);
            margin-top: 0.5rem;
        }

        .file-size {
            height: 1.2rem;
            font-size: 1.2rem;
            color: #6d6e7b;
            margin: 0.9rem 0;
        }
    }

    .file-img {
        flex: 0.3;
        width: 80px;
        height: 80px;
        object-fit: contain;
    }
}

.show-area {
    width: 100%;
    height: 80vh;
    @include flex-layout(flex, center, center);
    background-color: rgba(35, 35, 35, 0.6);

    .show-picture {
        max-width: 100%;
        max-height: 100%;
    }

    .play-video {
        max-width: 100%;
        max-height: 100%;
    }
}

.imageSlot {
    width: 100%;
    height: 100%;
    max-width: 100%;
    max-height: 100%;
    overflow: hidden;
    @include flex-layout(flex, center, center);
}
</style>
